<template>
  <div class="proc-info">
    <el-drawer v-model="open" :size="800" title="详情" :destroy-on-close="true" @close="close">
      <template #default>
        <div class="body" v-if="!loading">
          <div class="info">
            <div class="title">{{procInst.procName}}</div>
            <div class="number">审批编号：{{procInst.procInstId}}</div>
<!--            <div class="submit-time">提交时间：{{procInst.submitTime}}</div>-->
            <img v-if="approvalStatusIcon != null" class="approve_status_icon" :src="approvalStatusIcon" />
          </div>

          <div class="form">
            <v-form-render ref="vFormRef" :form-json="formJson" :form-data="formData" :option-data="optionData" />
          </div>
          <div class="record" v-if="approvalRecords != null">
            <ProcApprovalRecord :records="approvalRecords" />
          </div>
        </div>

      </template>
      <template #footer v-if="!loading && procInst && procInst.runStatus === '1' && (procInst.needApproval || procInst.owner)">
        <div class="footer">
          <div class="left">
            <div class="btn" v-if="procInst && procInst.allowRevoke === 1 && procInst.owner" @click="showRevoke">撤消</div>
            <template v-if="procInst.needApproval && APPROVER === procInst.handleNodeType">
              <div class="btn" v-if="procInst.allowAddSign === 1" @click="showAddSign">加签</div>
              <div class="btn" v-if="procInst.allowForward === 1" @click="showForward">转交</div>
              <div class="btn" v-if="procInst.allowRollback === 1" @click="showRollback">退回</div>
            </template>
          </div>
          <div class="right" v-if="procInst.needApproval">
            <div class="btn default" v-if="APPROVER === procInst.handleNodeType" @click="showApprove(2)">拒绝</div>
            <div class="btn primary" v-if="APPROVER === procInst.handleNodeType" @click="showApprove(1)">同意</div>
            <div class="btn primary" v-if="START === procInst.handleNodeType" @click="doApproval(true)">提交</div>
          </div>
        </div>
      </template>
    </el-drawer>

    <!-- 审批 -->
    <el-dialog v-model="approveDialog" :title="approveTitle" width="500">
      <el-input
          v-model="approveOpinion"
          style="width: 100%"
          :autosize="{ minRows: 4, maxRows: 4 }"
          type="textarea"
          placeholder="请输入审批意见……"
      />
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="approveDialog = false">取消</el-button>
          <el-button type="primary" @click="doApproval(false)">确定</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 撤消申请 -->
    <el-dialog v-model="revokeDialog" title="撤消申请" width="500">
      <span>你确定要撤消申请吗？</span>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="revokeDialog = false">取消</el-button>
          <el-button type="primary" @click="doRevoke">确定</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 加签 -->
    <el-dialog v-model="addSignDialog" title="加签" width="500">
      <div class="add-sign">
        <div class="sign-item">
          <div class="sign-title">加签审批人</div>
          <div class="sign-body">
            <OrgSelectView v-model="toUser" :multipleSize="1" />
          </div>
        </div>

        <div class="sign-item">
          <div class="sign-title">加签方式</div>
          <div class="sign-body">
            <el-select v-model="addSignType" placeholder="请选择加签方式" style="width: 100%">
              <el-option label="前加签" value="1"/>
              <el-option label="后加签" value="2"/>
            </el-select>
            <div class="sign-type-desc">{{addSignTypeDesc}}</div>
          </div>
        </div>

        <div class="sign-item" v-if="addSignType === '2'">
          <div class="sign-title">审批同意意见</div>
          <div class="sign-body">
            <el-input
                v-model="approveOpinion"
                style="width: 100%"
                :autosize="{ minRows: 4, maxRows: 4 }"
                type="textarea"
                placeholder="请输入审批同意意见……"
            />
          </div>
        </div>

        <div class="sign-item">
          <div class="sign-title">加签备注</div>
          <div class="sign-body">
            <el-input
                v-model="remark"
                style="width: 100%"
                :autosize="{ minRows: 4, maxRows: 4 }"
                type="textarea"
                placeholder="请输入加签备注……"
            />
          </div>
        </div>
      </div>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="addSignDialog = false">取消</el-button>
          <el-button type="primary" @click="doAddSign">确定</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 转交 -->
    <el-dialog v-model="forwardDialog" title="转交" width="500">
      <div class="forward">
        <div class="forward-item">
          <div class="forward-title">转交审批人</div>
          <div class="forward-body">
            <OrgSelectView v-model="toUser" :multipleSize="1" />
          </div>
        </div>

        <div class="forward-item">
          <div class="forward-title">转交备注</div>
          <div class="forward-body">
            <el-input
                v-model="remark"
                style="width: 100%"
                :autosize="{ minRows: 4, maxRows: 4 }"
                type="textarea"
                placeholder="请输入转交备注……"
            />
          </div>
        </div>
      </div>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="forwardDialog = false">取消</el-button>
          <el-button type="primary" @click="doForward">确定</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 退回 -->
    <el-dialog v-model="rollbackDialog" title="退回" width="500">
      <div class="rollback">
        <div class="rollback-item">
          <div class="rollback-title">退回到</div>
          <div class="rollback-body">
            <el-select v-model="toNodeId" placeholder="请选择退回到" style="width: 100%">
              <el-option v-for="node in rollbackNodes" :label="node.nodeName" :value="node.nodeId">
                <div class="select-option">
                  <span class="option-left">{{ node.nodeName }}</span>
                  <span class="option-right">{{ node.describe }}</span>
                </div>
              </el-option>
            </el-select>
          </div>
        </div>

        <div class="rollback-item">
          <div class="rollback-title">审批意见</div>
          <div class="rollback-body">
            <el-input
                v-model="approveOpinion"
                style="width: 100%"
                :autosize="{ minRows: 4, maxRows: 4 }"
                type="textarea"
                placeholder="请输入审批意见……"
            />
          </div>
        </div>
      </div>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="rollbackDialog = false">取消</el-button>
          <el-button type="primary" @click="doRollback">确定</el-button>
        </div>
      </template>
    </el-dialog>
  </div>

</template>

<script setup name="ProcInstInfo">
import ProcApprovalRecord from "./ProcApprovalRecord.vue"
import OrgSelectView from "@/components/OrgSelect/OrgSelectView.vue";
import { getInst, getApprovalRecord } from "@/api/bpm/inst";
import {approval, revoke, addSign, forward, getRollbackNodes, rollback} from "@/api/bpm/approval";
import {START, APPROVER} from "@/components/EasyProcess/config/nodeType";
import {getApprovalStatusIcon} from "@/views/bpm/components/BpmIcon";
import {getCurrentInstance, nextTick, reactive, ref, defineEmits, computed} from "vue";

const { proxy } = getCurrentInstance();

const emit = defineEmits(["close"]);
const open = ref(false);
const approveDialog = ref(false);
const revokeDialog = ref(false);
const addSignDialog = ref(false);
const forwardDialog = ref(false);
const rollbackDialog = ref(false);
const addSignType = ref("1");
const toUser = ref([]);
const toNodeId = ref(null);
const rollbackNodes = ref([]);
const approveTitle = ref(null);
const approveResult = ref(null);
const approveOpinion = ref(null);
const remark = ref(null);
const loading = ref(true);
const vFormRef = ref(null);
const procInst = ref(null);
let optionData = reactive({});
let formJson = reactive({});
let formData = reactive({});
let approvalRecords = ref(null);
let procInstId = null;
let approvalStatusIcon = ref(null);

function show(id) {
  reset()
  procInstId = id
  open.value = true
  init()
}

function reset() {
  loading.value = true
  approveTitle.value = null
  approveResult.value = null
  approveOpinion.value = null
  remark.value = null
  toUser.value = []
  procInst.value = null
  optionData = {}
  formJson = {}
  formData = {}
  approvalRecords.value = null
}

function init() {
  getInst(procInstId).then(response => {
    procInst.value = response.data
    formJson = procInst.value.formConfig
    formData = procInst.value.formData
    approvalStatusIcon.value = getApprovalStatusIcon(procInst.value.approvalStatus)
    loading.value = false
    handlePermissions()
  });

  getApprovalRecord(procInstId).then(response => {
    approvalRecords.value = response.data
  });

}


function handlePermissions() {
  nextTick(() => {
    let permissions = procInst.value.permissions
    let fieldWidgets = vFormRef.value.getFieldWidgets()
    let disableWidgets = []
    let enableWidgets = []
    let hideWidgets = []
    if (fieldWidgets) {
      fieldWidgets.forEach(item => {
        let rule = 2
        if (permissions) {
          let fieldPerm = permissions[item.name]
          if (fieldPerm) {
            rule = fieldPerm.rule
          }
        }

        if (rule === 3) {
          hideWidgets.push(item.name)
        } else if (rule === 1 || procInst.value.runStatus === '2') {
          enableWidgets.push(item.name)
        } else if (rule === 2) {
          disableWidgets.push(item.name)
        }
      })
    }

    if (procInst.value.runStatus === '2') {
      vFormRef.value.disableWidgets(disableWidgets)
      vFormRef.value.disableWidgets(enableWidgets)
    } else {
      vFormRef.value.disableWidgets(disableWidgets)
      vFormRef.value.enableWidgets(enableWidgets)
    }
    vFormRef.value.hideWidgets(hideWidgets)
  })
}

function showApprove(handleResult) {
  approveResult.value = handleResult
  if (handleResult === 1) {
    approveTitle.value = '审批同意意见'
  } else {
    approveTitle.value = '审批拒绝意见'
  }
  approveOpinion.value = null
  approveDialog.value = true
}

function doApproval(submit = false) {
  vFormRef.value.getFormData().then(formData => {
    if (!submit && !isAllowOpinionEmpty()) {
      proxy.$modal.msgError("请填写审批意见");
      return
    }
    let data = {
      procInstId: procInstId,
      formData: formData,
      handleResult: submit ? 1 : approveResult.value,
      handleOpinion: submit ? '' : approveOpinion.value,
      recordId: procInst.value.handleRecordId
    }

    approval(data).then(response => {
      approveDialog.value = false
      approveOpinion.value = null
      approveResult.value = null
      init()
      proxy.$modal.msgSuccess("提交成功");
    });
  }).catch(error => {
    // Form Validation failed
    proxy.$modal.msgError(error);
  })
}

function isAllowOpinionEmpty() {
  if (procInst.value.allowOpinionEmpty !== 1 && (approveOpinion.value == null || approveOpinion.value.length === 0)) {
    return false
  }
  return true
}

/**
 * 撤消申请
 */
function showRevoke() {
  revokeDialog.value = true
}
function doRevoke() {
  let data = {
    procInstId: procInstId
  }

  revoke(data).then(response => {
    proxy.$modal.msgSuccess("提交成功");
    init()
    revokeDialog.value = false
  });
}

/**
 * 加签
 */
function showAddSign() {
  addSignType.value = '1'
  toUser.value = []
  approveOpinion.value = null
  remark.value = null
  addSignDialog.value = true
}
function doAddSign() {
  if (toUser.value.length === 0) {
    proxy.$modal.msgError("请添加加签人")
    return
  }
  if (!isAllowOpinionEmpty()) {
    proxy.$modal.msgError("请填写审批意见");
    return
  }
  let data = {
    procInstId: procInstId,
    recordId: procInst.value.handleRecordId,
    addSignType: addSignType.value,
    handleOpinion: approveOpinion.value,
    remark: remark.value,
    toUserId: toUser.value[0].id,
  }

  addSign(data).then(response => {
    proxy.$modal.msgSuccess("提交成功");
    init()
    addSignDialog.value = false
  });
}

const addSignTypeDesc = computed(()=> {
  if (addSignType.value === '1') {
    return "加签后，流程先经过被加签人"
  } else if (addSignType.value === '2') {
    return "加签后，流程会执行同意并加签"
  }
  return ""
})


/**
 * 转交
 */
function showForward() {
  toUser.value = []
  remark.value = null
  forwardDialog.value = true
}
function doForward() {
  if (toUser.value.length === 0) {
    proxy.$modal.msgError("请添加转交人")
    return
  }
  let data = {
    procInstId: procInstId,
    recordId: procInst.value.handleRecordId,
    remark: remark.value,
    toUserId: toUser.value[0].id,
  }

  forward(data).then(response => {
    proxy.$modal.msgSuccess("提交成功");
    init()
    forwardDialog.value = false
  });
}

/**
 * 回退
 */
function showRollback() {
  let data = {
    procInstId: procInstId,
    recordId: procInst.value.handleRecordId,
  }
  getRollbackNodes(data).then(response => {
    rollbackNodes.value = response.data
    approveOpinion.value = null
    toNodeId.value = null
    rollbackDialog.value = true
  });

}
function doRollback() {
  let data = {
    procInstId: procInstId,
    recordId: procInst.value.handleRecordId,
    handleOpinion: approveOpinion.value,
    toNodeId: toNodeId.value,
  }

  rollback(data).then(response => {
    proxy.$modal.msgSuccess("提交成功");
    init()
    rollbackDialog.value = false
  });
}

function close() {
  open.value = false;
  emit("close");
}
defineExpose({
  show,
});
</script>

<style scoped lang="scss">
.proc-info {
  .body {
    width: 100%;
    background-color: #F2F3F5;
    .info {
      width: 100%;
      position: relative;
      background-color: #FFFFFF;
      padding: 0px 16px 16px 16px;

      .number {
        font-size: 12px;
        color: #909399;
        margin-bottom: 10px;
      }
      .title {
        margin-bottom: 10px;
        font-size: 18px;
        font-weight: bold;
        color: #303133;
      }
      .submit-time {
        font-size: 12px;
        color: #909399;
        margin-bottom: 10px;
      }
      .approve_status_icon {
        position: absolute;
        right: 20px;
        top: 0;
        width: 80px;
        height: 80px;
      }
    }
    .form {
      width: 100%;
      padding: 16px;
      background-color: #FFFFFF;
      margin-top: 10px;
    }
    .record {
      width: 100%;
      padding: 16px;
      margin-top: 10px;
      background-color: #FFFFFF;
    }
  }
  .footer {
    width: 100%;
    height: 50px;
    line-height: 50px;
    display: flex;
    //justify-content: center;
    align-items: center;
    background-color: #f2f3f5;
    box-shadow: 0 -3px 10px 1px #ccc;

    .left {
      display: flex;
    }
    .right {
      display: flex;
      margin-left: auto;
    }

  }

  .btn {
    height: 100%;
    width: 80px;
    cursor: pointer;
    text-align: center;
  }
  .btn:hover {
    background-color: #ffffff;
  }

  .primary {
    background-color: rgba(30, 131, 233, 0.8);
    color: #FFFFFF;
  }
  .primary:hover {
    background-color: rgba(30, 131, 233, 1)!important;
  }

  .default {
    background-color: #ffffff;
  }
  .default:hover {
    background-color: #ccc;
  }

  :deep(.el-drawer__footer) {
    padding: 0!important;
  }
  :deep(.el-drawer__body) {
    padding: 0!important;
  }
}

.add-sign {
  width: 100%;
  .sign-item {
    width: 100%;
    margin-bottom: 18px;
    .sign-title {
      margin-bottom: 18px;
    }
    .sign-body {
      .sign-type-desc {
        font-size: 12px;
        color: #909399;
        margin-top: 10px;
        text-align: right;
      }
    }
  }
}

.forward {
  width: 100%;
  .forward-item {
    width: 100%;
    margin-bottom: 18px;
    .forward-title {
      margin-bottom: 18px;
    }
    .forward-body {

    }
  }
}

.rollback {
  width: 100%;
  .rollback-item {
    width: 100%;
    margin-bottom: 18px;
    .rollback-title {
      margin-bottom: 18px;
    }
    .rollback-body {

    }
  }
}

.select-option {
  .option-left {
    float: left
  }
  .option-right {
    float: right;
    color: #909399;
    font-size: 13px;
  }
}
</style>